package com.yfs.cloud.util;

import java.util.Base64;
import java.util.Date;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yfs.cloud.commons.BusinessException;
import com.yfs.cloud.commons.Constants;
import com.yfs.cloud.commons.ResultCode;
import com.yfs.cloud.config.BusinessProperties;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

/**
* @Company: 影法師工作室
* @Description: jwt 工具类, 注意, 网关中的 jwt 工具类只需要有解析方法就行了. 因为网关不负责jwt的生成, 而用户微服务需要生成令牌, 所以用户微服务中的 JWTUtil 中只需要提供 创建 jwt 的方法就行了. 所有的微服务都不需要辅负责 jwt 的解析工作
* @author 影法師  
* @date 2020年8月24日 下午11:13:21 
* @version V1.0
 */
@SuppressWarnings("all")
@Component
public class JWTUtil {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private BusinessProperties businessProperties;

	/**
	* @Description: 生成加密后的秘钥 secretKey 
	* @author 影法師 
	* @date 2020年8月25日 上午12:08:41 
	* @version V1.0 
	* @param @return    
	* @return SecretKey    
	* @throws
	 */
	private SecretKey generalKey() {
		// jwtSecret 没取好的话, 会报 Last unit does not have enough valid bits,
		// 原因应该是编码后的URL长度不符合要求（要求长度是4的倍数），导致的这个问题
		byte[] encodedKey = Base64.getDecoder().decode(businessProperties.getJwt().getSecret());
		SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
		return key;
	}

	/**
	* @Description: 校验 jwt 
	* @author 影法師 
	* @date 2020年8月25日 上午12:09:54 
	* @version V1.0 
	* @param @param jwt
	* @param @return    
	* @return Claims    
	* @throws
	 */
	public Claims checkJWT(String jwt) {
		SecretKey secretKey = generalKey();
		try {
			// 设置解析的密钥
			return Jwts.parser().setSigningKey(secretKey)
					// 解析 token
					.parseClaimsJws(jwt)
					// 得到 payload
					.getBody();
		} catch (UnsupportedJwtException e) {
			logger.info("jwt : {} 签名不被支持", jwt);
			throw new BusinessException(ResultCode.JWT_INVALID);
		} catch (MalformedJwtException e) {
			logger.info("jwt : {} 登陆令牌格式错误", jwt);
			throw new BusinessException(ResultCode.JWT_INVALID);
		} catch (SignatureException e) {
			logger.info("jwt : {} 验签错误", jwt);
			throw new BusinessException(ResultCode.JWT_INVALID);
		} catch (IllegalArgumentException e) {
			logger.info("jwt : {} 登陆令牌非法", jwt);
			throw new BusinessException(ResultCode.JWT_INVALID);
		} catch (ExpiredJwtException e) {
			logger.info("jwt : {} 过期", jwt);
			throw new BusinessException(ResultCode.JWT_EXPIRE);
		}
	}

}